<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    什么是原型呢？如何回答呢？
    每一个对象都与另外一个对象相关联，那个关联的对象就被称为原型。
    例如：函数Person有一个属性prototype，指向一个对象，对于普通函数来说没多意义，对于构造函数就有作用了，
    当使用new操作符时，会把Person.prototype（原型对象）赋值给实例的__proto__（原型实例）属性。
    JS又有一个原型查找机制，，比如调用某个方法的时候，会去实例本身上找，没找到会自动去实例的__prototype__上查找

    为什么要设计原型对象呢？
    当我们每new一个构造函数的时候，生成的实例是不同的对象，所以即使共有的属性也不是共享的，修改其中一个属性，另外一个不会改变
    所以要设计一个对象专门用来存储对象共享的属性

    什么是原型链呢？
    每一个对象都有一个原型对象与之关联，这个原型对象它也是一个普通对象，这个普通对象也有自己的原型对象，这样层层递进，就形成了一个链条
    这个链条就是原型链。


    如何访问一个对象的原型？？
    不要直接obj.proto,而是采用es6新增的Reflect.getPrototypeOf或者Object.getPrototypeOf方法
    <script>
        function Foo(){
            getName=function(){
                console.log(1)
            }
            return this
        }
        Foo.getName=function(){
            console.log(2)
        }
        Foo.prototype.getName=function(){
            console.log(3)
        }
        var getName=function(){
            console.log(4)
        }

        function getName(){
            console.log(5)
        }
        Foo.getName()//2
        //为什么？其实这儿考察的是变量提示，函数声明优先级高于函数表达式，所以实际上是把函数getName提到上面，下面才是表达式的getName，
        //表达式的getName实际上就是一个变量，之后才赋值的，所以看似函数声明在下面，函数表达式在上面，要看提升后。
        getName()//4
        //因为执行Foo函数之后，往全局定义了一个getName的函数，注意，函数在哪儿执行的就在哪儿定义的，所以他肯定会覆盖函数表达式的getName
        Foo().getName()//1
        getName()//1
        //为什么是2，实际上new的是Foo上面getName这个函数，而在new的时候会执行这个getName构造函数，所以打印2
        new Foo.getName()//2
        // 为什么是3，这里new的是Foo，得到实例之后去访问原型对象中的getName方法
        new Foo().getName()//3
        //2个new怎么看呢？
        //第一个new，new 后面的东西，而后面的东西，就是正常的new Foo()得到实例，然后访问getName，而第一个new，就是new getName()
        //所以得到的是getName的实例,而打印的就是Foo原型上的那个getName方法
        new new Foo().getName()//3
    </script>
</body>

</html>